﻿import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import FilUI

import "../controls"
import "../view"
import "../test"
import SecAssistPro

Rectangle {
    id: control
    objectName: "ServicePage"

    property real pathBarHeight: 25
    property real footerHeight: 30
    property StackView parentStackView
    property alias downloading      : id_filradiusbutonn__download.loading
    property alias uploading        : id_filradiusbutonn__upload.loading
    property string user_agent      : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0"

    color: "transparent"

    ColumnLayout {
        anchors.fill: parent
        // spacing: 5
        anchors.leftMargin: 10
        anchors.rightMargin: 10
        Item {
            // width: parent.width
            // height: pathBarHeight
            Layout.preferredWidth: parent.width
            Layout.preferredHeight: pathBarHeight
            PathBarView {
                id: id_pathbarview__path
                anchors.fill: parent
                // 组件渲染完成时会发出一次此信号
                onGetPathBarPathList: {
                    getPathList()
                }
            }
        }
        Item {
            // width: parent.width
            // height:  parent.height - pathBarHeight
            Layout.preferredWidth: parent.width
            Layout.fillHeight: true
            FilSplitView {
                orientation: Qt.Horizontal
                anchors.fill: parent
                thickness: 4
                backgroundColor: "transparent"
                Item {
                    clip: true
                    SplitView.preferredWidth: 272
                    implicitHeight: parent.height
                    // FileListView {
                    //     id: id_filelistview__
                    //     anchors.fill: parent
                    // }
                    SelectableList {
                        id: id_selectablelist__list
                        anchors.fill: parent
                        singleSelectionMode: false
                        showStatusBar: false
                        itemHeight: 30
                        radius: 5

                        // 自定义颜色
                        normalColor: "#FFFFFF"
                        hoverColor: "#F0F0F0"
                        selectedColor: FilTools.withOpacity(FilTheme.primaryColor, 0.7)
                        selectedHoverColor: FilTools.withOpacity(FilTheme.primaryColor, 0.9)

                        // signal
                        onItemDoubleClicked: (name, type) => {
                            if (typeof name !== "string" || typeof type !== "string") {
                                console.warn("Invalid name or type string format")
                                return
                            }
                            if (type === "folder") {
                                id_pathbarview__path.entryFolder(name)
                            } else if (type === "file") {
                                // Download
                            } else {
                                console.warn("unknow type '%1'".arg(type))
                            }
                        }

                        // upload files
                        onUploadFiles: (files) => {
                            control.uploadBySelectableListView(files)
                        }
                    }
                }
                Item {
                    clip: true
                    SplitView.fillWidth: true
                    implicitHeight: parent.height
                    UserTableView {
                        id: id_usertableview
                        anchors.fill: parent
                        // anchors.bottomMargin: 20
                        parentStackView: control.parentStackView
                    }
                }
            }
        }
        Item {
            Layout.preferredHeight: footerHeight
            Layout.preferredWidth: parent.width
            Layout.topMargin: 0
            Layout.leftMargin: 5
            Layout.rightMargin: 5
            Layout.bottomMargin: 5
            Row {
                spacing: 10
                anchors.fill: parent
                // FilLoadingButton {
                //     width: 100
                //     text: (String.fromCharCode(FilIcons.Download).toString(16))
                //     font.family: font_loader.name
                //     loading: true
                // }
                // FilLoadingButton {
                //     width: 100
                //     text: (String.fromCharCode(FilIcons.Upload).toString(16))
                //     font.family: font_loader.name
                // }
                FilRadiusButtonn {
                    id: id_filradiusbutonn__download
                    anchors.verticalCenter: parent.verticalCenter
                    width: 128
                    height: 28
                    text: qsTr("Download")
                    onClicked: {
                        control.download()
                    }
                }
                FilRadiusButtonn {
                    id: id_filradiusbutonn__upload
                    anchors.verticalCenter: parent.verticalCenter
                    width: 128
                    height: 28
                    text: qsTr("Upload")
                    onClicked: {
                        control.upload()
                    }
                }
                FilProgressBar {
                    id: id_filprogressbar
                    anchors.verticalCenter: parent.verticalCenter
                    indeterminate: false
                    progressVisible: true
                    visible: value > 0
                }
                Item { width: 20; height: parent.height} // 给前边的FilProgressBar空出'%'的空间
                FilText {
                    id: id_filtext__file
                    anchors.verticalCenter: parent.verticalCenter
                }
            }
        }
    }

    /***************************  漫游式引导  ********************************/
    FilTour {
        id: id_filtour__servicepage
        steps: [
            // { title: qsTr(""), description: qsTr(""), target:()= },
            // Browse Bar
            { title: qsTr("Browse Bar"), description: qsTr("Display the current browsing information."), target:()=>id_pathbarview__path },
            { title: qsTr("Refresh"), description: qsTr("Refresh the current list of browsed files. This is the same as the refresh method used on the web page."), target:()=>id_pathbarview__path.filIconButton__refresh },
            { title: qsTr("Return"), description: qsTr("Click to return to the parent directory."), target:()=>id_pathbarview__path.filIconButton__return },
            { title: qsTr("Breadcrumb Bar"), description: qsTr("The current browsing path information. The left bottom part will display all the file information under the current path. You can select the files you want to download by clicking on the entries."), target:()=>id_pathbarview__path.filBreadcrumbBar__path },
            { title: qsTr("Countdown"), description: qsTr("Display the countdown time. When the countdown ends, the file list will be automatically refreshed."), target:()=>id_pathbarview__path.filText__countdown },
            // User Table View
            { title: qsTr("Switch Download Mode"), description: qsTr("Here, you can switch the download mode. In the default mode, all files will be downloaded to the designated location. In the project mode, files will be downloaded to the corresponding project directory."), target:()=>id_usertableview.filIconButton__switchDownloadMode },
            { title: qsTr("Add Project"), description: qsTr("After clicking the mouse, you will enter the new project setup guide page. On this page, you can configure the project name and the working directory."), target:()=>id_usertableview.filIconButton__add },
            { title: qsTr("Remove Project"), description: qsTr("After clicking the mouse, you will be asked if you want to delete the selected project."), target:()=>id_usertableview.filIconButton__remove },
            { title: qsTr("Current Selection"), description: qsTr("Here you can see the currently selected project. You can select the current project information by clicking on the entries in the table below."), target:()=>id_usertableview.rectangle__currentSelection },
            { title: qsTr("Override File"), description: qsTr("Overwrite the file with the same name when the download is complete."), target:()=>id_usertableview.filIconButton__override },
            // Downlaod and upload
            { title: qsTr("Download"), description: qsTr("In the list of files above, select the file you want to download. The downloaded file will be saved in the project work directory selected in the user table view."), target:()=>id_filradiusbutonn__download },
            { title: qsTr("Upload"), description: qsTr("In the user table view, select and configure the list of files that need to be uploaded, and after clicking the upload button, the files will be uploaded one by one to the server."), target:()=>id_filradiusbutonn__upload },
        ]
    }
    Timer {
        id: id_timer__startTour
        interval: 100
        onTriggered: {
            id_filtour__servicepage.open()
        }
    }
    function loadTour() {
        if (AppInfo.debugEnable) {
            console.log("loadTour debugEnable, not load tour")
            return
        }
        if (!TourTools.readRecord(objectName)) {
            id_timer__startTour.restart()
            TourTools.addRecord(objectName)
        }
    }

    /***********************************************************************/

    /*************************  更新当前文件列表  *****************************/
    property string autoSelectedPath: "/"
    NetworkCallable {
        id: id_networkcallable__getPathList
        onStart: {
            id_pathbarview__path.state = "busy"
        }
        onFinish: {
            id_pathbarview__path.state = "idle"
            id_pathbarview__path.restartCountDown()
        }
        onError: (status, errorString, result) => {
            id_pathbarview__path.errorFolder()
            console.debug(status + ";" + errorString + ";" + result)
        }
        onCache: (result) => {
            console.debug(result)
        }
        onSuccess: (result) => {
            id_pathbarview__path.okFolder()
            console.debug(result)
            parseJsonToList(result)
        }
    }
    function getPathList() {
        if (AppInfo.debugEnable) {
            console.log("getPathList debugEnable")
            return ;
        }
        var currentPath = id_pathbarview__path.getRequestPath()
        console.log("Current Path: " + currentPath)
        var url = SettingsHelper.getWebUrl()
        var request_url = url + "/index.php?explorer/pathList&path=%1".arg(currentPath)
        console.log("url=" + request_url)
        Network.get(request_url)
        .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0")
        .bind(control)
        .go(id_networkcallable__getPathList)
    }
    function parseJsonToList(jsonstr) {
        if (typeof jsonstr !== "string") {
            console.warn("Invalid json string")
            return
        }
        var selectable_list = []
        var json = JSON.parse(jsonstr)
        if (json["code"] === false) {
            console.warn("code is false, terminate parse")
            return
        }
        // 清理item前先将已选中的item拿出来，如果在新的filelist中包含了之前已选中的文件，则自动设置为已选中状态
        var selectItems
        var reqStr = id_pathbarview__path.getRequestPath()
        console.log("autoSelectedPath:", autoSelectedPath, "reqStr:", reqStr)
        if (autoSelectedPath === reqStr) {
            selectItems = JSON.parse(JSON.stringify(id_selectablelist__list.getSelectedItems()))
        } else {
            // 判断每次路径如果有变更则不需要根据已选择过item进行选择
            selectItems = []
            autoSelectedPath = reqStr
        }
        // 清理先前保存的items，然后根据请求到的新filelist更新UI
        id_selectablelist__list.clearItem()
        console.log("selectItems:", JSON.stringify(selectItems))
        var data = json["data"]
        var filelist = data["filelist"]
        if (filelist.length > 0) {
            for (var i = 0; i < filelist.length; i++) {
                var selected = false
                for (var k = 0; k < selectItems.length; k++) { // 遍历之前已选中的文件
                    if (filelist[i]["name"] === selectItems[k]["name"]) {
                        console.log("Matched selected file", filelist[i]["name"])
                        selected = true
                    }
                }
                if (selected) {
                    filelist[i]["selected"] = true
                }
                id_selectablelist__list.addItem(filelist[i])
            }
        }
        var folderlist = data["folderlist"]
        if (folderlist.length > 0) {
            for (var j = 0; j < folderlist.length; j++) {
                id_selectablelist__list.addItem(folderlist[j])
            }
        }
        console.log("parseJsonToList Parse Complete.")
    }
    /***********************************************************************/


    /***************************** 下载文件按钮 ******************************/
    property var downloadFiles: []
    property int downloadIndex: 0
    property var downloadStartTime
    property var downloadEndTime
    NetworkCallable {
        id: id_networkcallable__download
        onStart: {
            control.downloading = true
        }
        onFinish: {

        }
        onError: (result) => {
            showError(result)
            console.warn("download failure, terminate the download process. reason: ", result)
            control.downloading = false
            id_filtext__file.text = ""
            id_filprogressbar.value = 0.0
        }
        onSuccess: (result) => {
            console.log("download succeed, path: ", result)
            // get header
            var isHtml = false
            var isSecError = false
            var contentType = replyGetHeader("Content-Type")
            if (contentType.length > 0) {
                console.log("Content-Type:", contentType)
                if (contentType.includes("text/html")) {
                    console.log("includes text/html, start check HTML format")
                    var fileData = FilTools.readFile(result)
                    isHtml = isHtmlContent(fileData)
                    console.log("isHtml:", isHtml)
                    if (isHtml && fileData.includes("文件防泄密网关") && fileData.includes("用户名") && fileData.includes("密码") && fileData.includes("登录")) {
                        console.warn("The server returned the login page information, but there might be an error in the network request.")
                        isSecError = true
                        FilTools.removeFile(result)
                    }
                }
            }
            if (!isSecError) {
                if (downloadIndex == downloadFiles.length - 1) {
                    control.downloading = false
                    downloadEndTime = new Date().getTime()
                    var takeTime = downloadEndTime - downloadStartTime
                    showSuccess(qsTr("Download Succeed %1s").arg(takeTime/1000), 2000)
                    id_filtext__file.text = ""
                    id_filprogressbar.value = 0.0
                    // run script
                    var pid = id_usertableview.getCurrentSelectProjectPid()
                    var rdsstr = ProjectDbHelper.readRecordByPid(pid, ProjectDbHelperColumnIndexType.CIT_RDS)
                    console.log("pid:", pid, "rdsstr:", rdsstr)
                    if (rdsstr.length > 0) {
                        var rds = Number(rdsstr)
                        if (rds === 1) {
                            ProjectDbHelper.runDownloadScript(pid)
                        }
                    }
                } else {
                    downloadIndex++
                    downloadNext()
                }
            } else {
                showError(qsTr("Server has returned to the login page. Please try to log in again."), 0)
                control.downloading = false
                id_filtext__file.text = ""
                id_filprogressbar.value = 0.0
            }
        }
        onDownloadProgress: (recv, total) => {
            // console.log("recv: %1 total :%2".arg(recv).arg(total))
            // console.log("progress %1%".arg(recv / total * 100))
            id_filprogressbar.value = recv / total
        }
    }
    function downloadNext() {
        var filename = downloadFiles[downloadIndex]["name"]
        var webpath = ""
        if (id_pathbarview__path.currentPath === "/") {
            webpath = "/" + filename
        } else {
            webpath = id_pathbarview__path.currentPath + "/" + filename
        }
        var hosturl = SettingsHelper.getWebUrl()
        var request_url = hosturl + "/index.php?explorer/fileDownload&path=%1".arg(webpath)
        var wdir = ""
        if (SettingsHelper.getAppDownloadMode() === 0) {
            wdir = SettingsHelper.getAppDownloadDir()
        } else if (SettingsHelper.getAppDownloadMode() === 1) {
            wdir = ProjectDbHelper.readRecordByPid(
                        id_usertableview.getCurrentSelectProjectPid(),
                        ProjectDbHelperColumnIndexType.CIT_WDIR)
        }
        var path = ""
        if (wdir.charAt(wdir.length - 1) === '/') {
            path = wdir + filename
        } else {
            path = wdir + "/" + filename
        }
        if (SettingsHelper.getAppDownloadOverride() === false) {
            path = FilTools.getUniqueFileName(path)
        }
        console.log("downloadNext request_url:", request_url, "path: ", path)

        if (AppInfo.debugEnable) {
            console.log("debug mode, not request download")
            return
        }

        var ingStr = qsTr("Downloading")
        id_filtext__file.text = ingStr + " " + filename

        Network.get(request_url)
        .addHeader("User-Agent", control.user_agent)
        // .openLog(true)
        .toDownload(path)
        .bind(control)
        .go(id_networkcallable__download)
    }

    function download() {
        var downlaodMode = SettingsHelper.getAppDownloadMode(0)
        if (downlaodMode === 0) {
        } else if (downlaodMode === 1) {
            var pidstr = id_usertableview.getCurrentSelectProjectPid()
            if (pidstr.length <= 0) {
                showInfo(qsTr("Please select the download directory"))
                return
            }
        } else {
            showError(qsTr("Error Download Mode"))
            return
        }
        downloadFiles = []
        downloadIndex = 0
        var selectItems = id_selectablelist__list.getSelectedItems()
        for (var i = 0; i < selectItems.length; i++) {
            downloadFiles.push(selectItems[i])
        }
        if (downloadFiles.length <= 0) {
            showInfo(qsTr("Please select the file you want to download from the left side"))
            return
        }
        console.log("download files: ", JSON.stringify(downloadFiles))
        downloadStartTime = new Date().getTime();
        downloadNext()
    }
    /***********************************************************************/
    /***************************** 上传文件按钮 ******************************/
    property var uploadFiles: []
    property int uploadIndex: 0
    NetworkCallable {
        id: id_networkcallable__uplaod
        onStart: {
            control.uploading = true
        }
        onFinish: {

        }
        onError: (result) => {
            showError(result)
            console.warn("upload failure, terminate the upload process. reason: ", result)
            control.uploading = false
            id_filtext__file.text = ""
            id_filprogressbar.value = 0.0
        }
        onSuccess: (result) => {
            console.log("upload result: ", result)
            if (result.length > 0) {
                var jsonobj = JSON.parse(result)
                if (jsonobj) {
                    if (jsonobj["code"]) {
                        if (uploadIndex == uploadFiles.length - 1) {
                            control.uploading = false
                            showSuccess(jsonobj["data"])
                            id_filtext__file.text = ""
                            id_filprogressbar.value = 0.0
                        } else {
                            uploadIndex++
                            uploadNext()
                        }
                        return
                    } else {
                        console.warn("The server returned that the upload failed. msg:", jsonobj["data"])
                        showError(jsonobj["data"])
                    }
                }
            }
            console.warn("upload may be failure, terminate the upload process")
            control.uploading = false
            id_filtext__file.text = ""
            id_filprogressbar.value = 0.0
        }
        onUploadProgress: (sent, total) => {
            // console.log("sent: %1 total :%2".arg(sent).arg(total))
            id_filprogressbar.value = sent / total
        }
    }
    function uploadNext() {
        var filename = uploadFiles[uploadIndex]
        var webdir = id_pathbarview__path.currentPath
        var hosturl = SettingsHelper.getWebUrl()
        var request_url = hosturl + "/index.php?explorer/fileUpload&path=%1".arg(webdir)

        if (AppInfo.debugEnable) {
            console.log("debug mode, not request upload")
            return
        }

        var ingStr = qsTr("Uploading")
        id_filtext__file.text = ingStr + " " + filename

        Network.postForm(request_url)
        .addHeader("User-Agent", control.user_agent)
        .setRetry(1) // once request
        .addFile("file", filename)
        .bind(control)
        .go(id_networkcallable__uplaod)
    }
    function upload() {
        uploadFiles = []
        uploadIndex = 0
        var pidstr = id_usertableview.getCurrentSelectProjectPid()
        if (pidstr.length <= 0) {
            showInfo(qsTr("Please select to upload the configuration file"))
            return
        }
        var jsonStr = ProjectFileWatcher.readFileDataByPid(pidstr)
        if (jsonStr.length <= 0) {
            showInfo(qsTr("Upload Files Config Not Found file"))
            return
        }
        var jsonobj = JSON.parse(jsonStr)
        var files = jsonobj["files"]
        if (!files) {
            showInfo(qsTr("Upload Files Config Not Found files object"))
            return
        }
        if (files.length <= 0) {
            showInfo(qsTr("Upload Files Config Count is Zero"))
            return
        }
        for (var i = 0; i < files.length; i++) {
            if (files[i]["enable"] && ProjectFileWatcher.exists(files[i]["path"])) {
                uploadFiles.push(files[i]["path"])
            }
        }
        if (uploadFiles.length <= 0) {
            showInfo(qsTr("No files selected for upload"))
            return
        }
        console.log("upload files: ", JSON.stringify(uploadFiles))
        var russtr = ProjectDbHelper.readRecordByPid(
                       pidstr,
                       ProjectDbHelperColumnIndexType.CIT_RUS)
        console.log("russtr ", russtr)
        if (russtr.length > 0) {
            var rus = Number(russtr)
            if (rus === 1) {
                ProjectDbHelper.runUploadScript(pidstr)
                console.log("upload done run script complete")
            }
        }
        uploadNext()
    }
    function uploadBySelectableListView(files) {
        uploadFiles = []
        uploadIndex = 0
        if (files.length <= 0) {
            showInfo(qsTr("uploadBySelectableListView invalid files"))
            return
        }
        for (var i = 0; i < files.length; i++) {
            uploadFiles.push(files[i])
        }
        console.log("uploadd files: ", JSON.stringify(uploadFiles))
        uploadNext()
    }

    /***********************************************************************/
    Component.onCompleted: {
        id_pathbarview__path.restartCountDown()
        loadTour()
    }

    StackView.onActivating: {
        console.log("StackView.onActivating")
        id_usertableview.refreshDataFromDatabase()
    }

    StackView.onDeactivating: {
        console.log("StackView.onDeactivating")
        // id_pathbarview__path.stopCountDown()
    }

    /***********************************************************************/
    /************************** 判断文本内容是否为html ************************/
    /***********************************************************************/
    // 主要的HTML检测正则表达式
    function isHtmlContent(content) {
        if (!content || content.length < 20) {
            return false;
        }
        var trimmedContent = content.trim();
        // 快速检查：开头特征
        if (isLikelyHtmlByPrefix(trimmedContent)) {
            return true;
        }
        // 综合正则表达式检测
        return checkWithRegexPatterns(trimmedContent);
    }
    // 检查内容开头特征
    function isLikelyHtmlByPrefix(content) {
        var first100 = content.substring(0, 100).toLowerCase();
        return first100.startsWith("<!doctype") ||
               first100.startsWith("<html") ||
               first100.startsWith("<!--") ||
               first100.startsWith("<head") ||
               first100.startsWith("<body");
    }
    // 使用正则表达式模式检测
    function checkWithRegexPatterns(content) {
        var lowerContent = content.toLowerCase();
        // 定义HTML特征正则表达式模式
        var patterns = [
            // 文档类型声明（最可靠的指标）
            /<!DOCTYPE\s+html\s*(?:PUBLIC\s+[^>]*)?>/i,

            // HTML标签结构
            /<html[^>]*>[\s\S]*<\/html>/i,
            /<head[^>]*>[\s\S]*<\/head>/i,
            /<body[^>]*>[\s\S]*<\/body>/i,
            // 常见的HTML标签对
            /<title[^>]*>[\s\S]*<\/title>/i,
            /<div[^>]*>[\s\S]*<\/div>/i,
            /<span[^>]*>[\s\S]*<\/span>/i,
            /<p[^>]*>[\s\S]*<\/p>/i,
            // 自闭合标签
            /<meta[^>]+>/i,
            /<link[^>]+>/i,
            /<img[^>]+>/i,
            /<br[^>]*>/i,
            /<hr[^>]*>/i,
            // 脚本和样式
            /<script[^>]*>[\s\S]*<\/script>/i,
            /<style[^>]*>[\s\S]*<\/style>/i,
            // HTML注释
            /<!--[\s\S]*?-->/,
            // 属性格式
            /<[a-z]+[^>]*\s+[a-z]+=(["'])[^"']*\1[^>]*>/i,
            // 常见的HTML实体
            /&(?:amp|lt|gt|quot|nbsp|copy|reg);/i,
            // 类选择器
            /class=(["'])[^"']*\1/i,
            /id=(["'])[^"']*\1/i
        ];
        // 计算匹配分数
        var score = 0;
        for (var i = 0; i < patterns.length; i++) {
            if (patterns[i].test(lowerContent)) {
                score++;

                // 如果找到高度可信的模式，立即返回
                if (patterns[i].toString().includes('DOCTYPE') ||
                    patterns[i].toString().includes('<html')) {
                    return true;
                }
            }
            // 达到足够分数就认为是HTML
            if (score >= 3) {
                return true;
            }
        }
        // 检查标签密度
        return checkTagDensity(lowerContent);
    }
    // 检查HTML标签密度
    function checkTagDensity(content) {
        // 匹配所有HTML标签
        var tags = content.match(/<[^>]+>/g);
        if (!tags || tags.length < 3) {
            return false;
        }
        // 计算标签密度
        var textContent = content.replace(/<[^>]+>/g, '');
        var tagDensity = tags.length / (tags.length + textContent.length);
        // 标签密度超过阈值且有一定数量的标签
        return tagDensity > 0.08 && tags.length >= 5;
    }
    // 增强版检测：包含内容结构分析
    function advancedHtmlDetection(content) {
        if (!content) return false;
        var lowerContent = content.toLowerCase();
        // 权重评分系统
        var score = 0;
        // 高权重特征（每个+3分）
        if (/<!DOCTYPE\s+html/i.test(lowerContent)) score += 3;
        if (/<html[^>]*>/i.test(lowerContent)) score += 3;
        if (/<head[^>]*>/i.test(lowerContent)) score += 3;
        if (/<body[^>]*>/i.test(lowerContent)) score += 3;
        // 中权重特征（每个+2分）
        if (/<title[^>]*>/i.test(lowerContent)) score += 2;
        if (/<meta[^>]+>/i.test(lowerContent)) score += 2;
        if (/<div[^>]*>/i.test(lowerContent)) score += 2;
        if (/<span[^>]*>/i.test(lowerContent)) score += 2;
        // 低权重特征（每个+1分）
        if (/<p[^>]*>/i.test(lowerContent)) score += 1;
        if (/<a[^>]*>/i.test(lowerContent)) score += 1;
        if (/<img[^>]*>/i.test(lowerContent)) score += 1;
        if (/<!--/.test(lowerContent)) score += 1;
        // 快速判断
        if (score >= 4) return true;
        // 如果分数较低，检查标签密度
        if (score > 0) {
            return checkTagDensity(lowerContent);
        }
        return false;
    }
}
